package smallfrench.moteur.biblio;

import java.util.HashMap;

import smallfrench.moteur.biblio.err.ErreurClasse;
import smallfrench.moteur.interp.RObjet;

/**
 * Un {@link RObjet} qui possède une classe {@link AClasse} avec un système
 * d’héritage.<br>
 * 
 * @author antoine1023
 */
public class AObjet extends RObjet {

	/**
	 * Les champs de l’objet
	 */
	public HashMap<String, RObjet> champs;

	/**
	 * Les instances des superclasses natives. Elles sont nécéssaires si on
	 * veut appeller une de leurs méthodes.
	 */
	HashMap<Class<?>, AObjet> supersObjetsNatifs;

	//------------------------------------------------------

	public AObjet() {
		champs = new HashMap<String, RObjet>();
		supersObjetsNatifs = new HashMap<Class<?>, AObjet>();
	}

	public AObjet(AClasse classe, HashMap<Class<?>, AObjet> supersObjetsNatifs) {
		super(classe);
		champs = new HashMap<String, RObjet>();
		this.supersObjetsNatifs = supersObjetsNatifs;
	}

	//------------------------------------------------------

	@Override
	public final RObjet getMembre(String nom) {

		RObjet f = classe.getMethode(nom);
		if (f != null) return f;

		return champs.get(nom);
	}

	@Override
	public boolean equals(Object objet) {
		return this == objet;
	}

	/**
	 * 
	 * @param classe
	 * @return Le super objet natif de la classe Java passée en paramètre
	 * @throws IllegalArgumentException Si la classe n’est pas une superclasse
	 * native de <code>this</code>
	 */
	public AObjet getSuperObjetNatif(Class<?> classe) {
		AObjet ao = supersObjetsNatifs.get(classe);
		if (ao == null) {
			throw new IllegalArgumentException(classe.getName()
					+ " n’est pas une superclasse native de " + this.classe);
		}
		return ao;
	}

	private final String ObjetEnChaine() {
		RObjet fEnChaine = classe.getMethode("enChaine");

		if (fEnChaine != null) {
			RObjet o = null;
			o = fEnChaine.appeler(this, new RObjet[] {});
			if (! (o instanceof RChaine))
				throw ErreurClasse.nouvelleException(o, "Chaine");
			return ((RChaine) o).valeur;
		}

		return "Objet";
	}

	@Override
	public RChaine enChaine() {
		return new RChaine(ObjetEnChaine());
	}

}
